package com.kaesun.ufit.hardware;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.os.Message;

import com.kaesun.ufit.serialport.SerialPort;
import com.kaesun.ufit.treadmill.MainApplication;
import com.kaesun.ufit.treadmill.WeakRefHandler;

public class CardioController {

	public static final int PKT_STX = 0xF1;
	public static final int PKT_ETX = 0xF2;

	public static final int CMD_START_STOP = 0xC1;
	public static final int CMD_SET_TIME = 0xC2;
	public static final int CMD_SET_AGE = 0xC3;
	public static final int CMD_SET_WEIGHT = 0xC4;
	public static final int CMD_SET_SPEED = 0xC5;
	public static final int CMD_SET_INCLINE = 0xC6;
	public static final int CMD_REQ_SPEED = 0xC7;
	public static final int CMD_REQ_INCLINE = 0xC8;
	public static final int CMD_REQ_HEARTRATE = 0xC9;
	public static final int CMD_REQ_CALORIE = 0xCA;
	public static final int CMD_REQ_TIME = 0xCB;
	public static final int CMD_REQ_DISTANCE = 0xCC;
	public static final int CMD_REQ_AUTO = 0xCD;
	public static final int CMD_SET_GOALHEARTRATE = 0xCE;

	public static final int RES_ACK = 0xD0;
	public static final int RES_START_STOP = 0xD1;
	public static final int RES_SPEED_WATTS = 0xD2;
	public static final int RES_INCLINE_RPM = 0xD3;
	public static final int RES_HEARTRATE = 0xD4;
	public static final int RES_CALORIE = 0xD5;
	public static final int RES_TIME = 0xD6;
	public static final int RES_DISTANCE = 0xD7;
	public static final int RES_AUTO_DATA = 0xD8;
	public static final int RES_ERROR = 0xD9;


	private static final String DEVICE_HALL_SENSOR = "/dev/ttyO4";
	private static final int BAUDRATE_HALL_SENSOR = 115200;

	private SerialPort mSerialPort = null;
	private ReadThread mReadThread = null;
	private WeakRefHandler mHandler = null;

	private OutputStream mOutputStream = null;

	public void start() {
		if (null == mSerialPort) {
			try {
				mSerialPort = new SerialPort(new File(DEVICE_HALL_SENSOR), BAUDRATE_HALL_SENSOR, 0);

				mReadThread = new ReadThread(mSerialPort);
				mReadThread.start();
				mOutputStream = mSerialPort.getOutputStream();
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public void stop() {
		if (null != mReadThread) {
			mReadThread.interrupt();
			mReadThread = null;
		}
		if (null == mSerialPort) {
			mSerialPort.close();
			mSerialPort = null;
		}
	}

	public void setHandler(WeakRefHandler handler) {
		mHandler = handler;
	}

	byte [] sendPacket = new byte [32];
	public String send(int cmd, int n) {
		int len = 0;

		sendPacket[len++] = (byte)PKT_STX;
		switch (cmd) {
		case CMD_START_STOP:
			sendPacket[len++] = (byte)3;	// len
			sendPacket[len++] = (byte)cmd;	// cmd
			sendPacket[len++] = (byte)(0!=n ? 0x52 : 0x45);	// data 0x52, 0x45
			break;
		case CMD_SET_TIME:
			sendPacket[len++] = (byte)6;	// len
			sendPacket[len++] = (byte)cmd;	// cmd
			sendPacket[len++] = (byte)((n/1000)%10 + '0');	// data
			sendPacket[len++] = (byte)((n/100)%10 + '0');	// data
			sendPacket[len++] = (byte)((n/10)%10 + '0');	// data
			sendPacket[len++] = (byte)((n/1)%10 + '0');		// data
			break;
		case CMD_SET_AGE:
		case CMD_SET_WEIGHT:
		case CMD_SET_SPEED:
		case CMD_SET_INCLINE:
		case CMD_SET_GOALHEARTRATE:
			sendPacket[len++] = (byte)5;	// len
			sendPacket[len++] = (byte)cmd;	// cmd
			sendPacket[len++] = (byte)((n/100)%10 + '0');	// data
			sendPacket[len++] = (byte)((n/10)%10 + '0');	// data
			sendPacket[len++] = (byte)((n/1)%10 + '0');		// data
			break;
		case CMD_REQ_SPEED:
		case CMD_REQ_INCLINE:
		case CMD_REQ_HEARTRATE:
		case CMD_REQ_CALORIE:
		case CMD_REQ_TIME:
		case CMD_REQ_DISTANCE:
		case CMD_REQ_AUTO:
			sendPacket[len++] = (byte)2;	// len
			sendPacket[len++] = (byte)cmd;	// cmd
			break;

		default:
			return "";
		}
		sendPacket[len++] = (byte)0;	// cs
		for (int i=1; i<len-1; i++) {
			sendPacket[len-1] += sendPacket[i];
		}
		sendPacket[len++] = (byte)PKT_ETX;

		try {
			mOutputStream.write(sendPacket, 0, len);
			mOutputStream.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}

		StringBuffer sb = new StringBuffer(len*3 + 1);
		for (int i=0; i<len; i++) {
			if (0x10 > ((int)sendPacket[i] & 0xFF)) {
				sb.append('0');
			}
			sb.append(Integer.toString(sendPacket[i] & 0xFF, 16));
			sb.append(' ');
		}
		return sb.toString();
	}

	public void zero() {
		try {
			mSerialPort.getOutputStream().write('Z');
		} catch (IOException e) {
			e.printStackTrace();
		}
	}


	private class ReadThread extends Thread {
		private InputStream mInputStream = null;

		public ReadThread(SerialPort sp) {
			mInputStream = sp.getInputStream();
		}

		@Override
		public void run() {
			super.run();

			if (null == mInputStream) {
				return;
			}

			byte[] buf = new byte[32];
			int size = 0;
			while (!isInterrupted()) {
				try {
					size = mInputStream.read(buf);
					if (null != mHandler) {
						mHandler.sendMessage(Message.obtain(mHandler, MainApplication.HANDLER_RX_CARDIOCONTROLLER, size, 0, buf));
					}

					/*StringBuffer sb = new StringBuffer(size*2 + 1);
					for (int i=0; i<size; i++) {
						if (0x10 > ((int)buf[i] & 0xFF)) {
							sb.append('0');
						}
						sb.append(Integer.toString(buf[i] & 0xFF, 16));
					}
					Log.e("AAA", "recv : " + sb.toString());*/
				} catch (IOException e) {
					e.printStackTrace();
					return;
				}
			}
		}
	}
}
